#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>



//--------------------员工信息结构体------------//
#define USER_LOGIN 		0x00000000  // login	登陆    0x00000001
#define USER_MODIFY 	0x00000001  // user-modification  修改
#define USER_QUERY 		0x00000002  // user-query   查询


#define ADMIN_LOGIN 	0x10000000  // login	登陆    0x00000001
#define ADMIN_MODIFY 	0x10000001 // admin_modification
#define ADMIN_ADDUSER 	0x10000002 // admin_adduser
#define ADMIN_DELUSER 	0x10000004 // admin_deluser
#define ADMIN_QUERY 	0x10000008  //hitory_query
#define ADMIN_HISTORY 	0x10000010  //hitory_query

#define ADMIN 0	//管理员
#define USER  1	//用户

#define QUIT 			0x11111111

#define NAMELEN 512
#define DATALEN 512
#define SQL_LEN 4096

char user_name[DATALEN] = {0};
/*员工基本信息*/
typedef struct staff_info{
    int no;              //员工编号
    int usertype;        //ADMIN(1) USER(2)
    char name[NAMELEN];  //姓名
    char passwd[8];      //密码
    int age; 		 //年龄
    char phone[NAMELEN]; //电话
    char addr[DATALEN];  //地址
    char work[DATALEN];  //职位
    char data[DATALEN];  //入职年月
    int level;           //等级
    double salary;       //工资
}staff_info_t;


/*定义双方通信结构体信息*/
typedef struct{
    int msgtype;            //请求的消息类型
    int usertype;           //ADMIN(1) USER(2)
    char username[NAMELEN]; //姓名
    char passwd[8];         //登录密码
    char recvmsg[DATALEN];  //通信的消息
    int flags;              //标志位
    staff_info_t info;      //员工信息
}MSG;


//-----------end----------//

staff_info_t staff;

//将用户名和密码发送到服务器数据库对比
int Login_inf(int socked, MSG *msg);

int callback(void *arg ,int f_num,char **f_value,char** f_name);
//-------------普通用户处理函数--------------//

/**************************************
 *函数名：do_query
 *参   数：消息结构体
 *功   能：登陆
 ****************************************/
void do_admin_query(int sockfd,MSG *msg)
{
    printf("------------%s-----------%d.\n",__func__,__LINE__);
    msg->msgtype = ADMIN_QUERY;
    msg->usertype = ADMIN;
    int i = 0;
    while(1)
    {
choose2:
        //选择查询界面
        puts("*************************************************************");
        puts("******* 1：按人名查找  	2：查找所有 	3：退出	 *******");
        puts("*************************************************************");
        puts("请输入您要操作的选项");
        int choose,i;
        scanf("%d",&choose);
        getchar();
        if(choose == 1)
        {
            msg->flags = 1; //按照人名查找
            printf("请输入您要查询的用户名\n");
            scanf("%s",msg->info.name);
            getchar();
            //发送修改后的结构体
            if(send(sockfd, msg, sizeof(MSG), 0) < 0){
                perror("send()");
            }
            printf("发送用户名成功\n");
            if(recv(sockfd,msg, sizeof(MSG), 0) < 0){
                perror("recv()");
            }
            //获取信息
            printf("工号   用户类型    姓名   密码   年龄   电话   地址   职位 入职年月   等级   工资\n");
            //打印所有信息
            printf("%-8d %-6d %-6s %-6s %-6d %-6s %-6s %-6s %-6s %-6d %-6f\n",\
                    msg->info.no,msg->info.usertype,msg->info.name,msg->info.passwd,msg->info.age,msg->info.phone,\
                    msg->info.addr,msg->info.work,msg->info.data,msg->info.level,msg->info.salary);

        }
        else if(choose == 2)
        {
            //查询所有用户
            msg->flags = 2; //查找所有
            //发送修改后的结构体
            if(send(sockfd, msg, sizeof(MSG), 0) < 0){
                perror("send()");
            }
            //获取信息
            printf("工号 用户类型 姓名 密码	年龄 电话 地址 职位	入职年月 等级   工资 \n");
            while(1)
            {
                if(recv(sockfd, msg, sizeof(MSG), 0) < 0){
                    perror("recv()");
                    break;
                }
                // printf("%d --- 查找所有\n",msg->flags);
                if(strncmp(msg->recvmsg,"END",2)==0){
                    printf("收到了end结束了\n");
                     strcpy(msg->recvmsg,"");
                    break;
                }
                printf("%-6d %-6d %-6s %-6s %-6d %-6s %-6s %-6s %-6s %-6d %-6f\n",\
                msg->info.no,msg->info.usertype,msg->info.name,msg->info.passwd,msg->info.age,msg->info.phone,\
                msg->info.addr,msg->info.work,msg->info.data,msg->info.level,msg->info.salary);
            }
        }else if(choose == 3){
            break;
        }   
        else{
            printf("输入错误\n");
            goto choose2;
        }
    }
}


/**************************************
 *函数名：admin_modification
 *参   数：消息结构体
 *功   能：管理员修改
 ****************************************/
void do_admin_modification(int sockfd,MSG *msg)//管理员修改
{
    printf("------------%s-----------%d.\n",__func__,__LINE__);
    int num,id;
    //输入要修改的ID,看是否存在该人
    puts("请输入您要修改的ID:");
    scanf("%d",&id);
    getchar();
    //发送ID，并确定是否存在
    msg->info.no = id;
    msg->msgtype = ADMIN_MODIFY;
    if(send(sockfd,msg,sizeof(MSG),0) == -1){
        printf("发送失败 %d \n",__LINE__);
        return;
    }
    if (recv(sockfd,msg,sizeof(MSG),0) == -1)
    {
        printf("fail to recv\n");
    }
    if (strncmp(msg->recvmsg,"YES",3) == 0)
    {
        printf("--------------------用户存在------------------------\n");
    }
    else{
        printf("用户不存在\n");
        return;
    }

    //请用户输入要修改的信息
Modify:
    printf("请选择要修改的信息\n");
    puts("*******************请输入要修改的选项********************");
    puts("******	1：姓名	   2：密码	3：年龄       4：电话  *****");
    puts("******	5：地址	   6：职位  7：入职年月   8：评级   ****");
    puts("******	9：工资	  10：退出				           ****");
    puts("********************************************************");
    printf("请输入您的选择（1~10）>> ");
    scanf("%d",&num);
    getchar();
    //根据选择发送不同修改信息
    switch (num)
    {
    case 1:
        msg->flags = 1;
        printf("请输入姓名>> ");
        scanf("%s",msg->info.name);getchar();
        break;
    case 2:
        msg->flags = 2;
        printf("请输入密码>> ");
        scanf("%s",msg->info.passwd);getchar();
        break;
    case 3:
        msg->flags = 3;
        printf("请输入年龄>> ");
        scanf("%d",&msg->info.age);getchar();
        break;
    case 4:
        msg->flags = 4;
        printf("请输入电话>> ");
        scanf("%s",msg->info.phone);getchar();
        break;
    case 5:
        msg->flags = 5;
        printf("请输入地址>> ");
        scanf("%s",msg->info.addr);getchar();
        break;
    case 6:
        msg->flags = 6;
        printf("请输入职位>> ");
        scanf("%s",msg->info.work);getchar();
        break;
    case 7:
        msg->flags = 7;
        printf("请输入入职年月>> ");
        scanf("%s",msg->info.data);getchar();
        break;
    case 8:
        msg->flags = 8;
        printf("请输入等级>> ");
        scanf("%d",&msg->info.level);getchar();
        break;
    case 9:
        msg->flags = 9;
        printf("请输入工资>> ");
        scanf("%lf",&msg->info.salary);getchar();
        break;
    case 10:
        break;
    default:
        printf("输入错误，请重新输入\n");getchar();
        goto Modify;
        break;
    }
    //发送消息
    msg->msgtype = ADMIN_MODIFY;
    //printf("run to %d \n",__LINE__);
    if (send(sockfd,msg,sizeof(MSG),0) == -1)
    {
        printf("fail to send \n");
        return;
    }else{
        if (recv(sockfd,msg,sizeof(MSG),0) == -1)
        {
            printf("fail to recv\n");
            return;
        }
        else{
            if (strncmp(msg->recvmsg,"YES",3) == 0)
            {
                printf("--------------------修改成功------------------------\n");
                return;
            }
            printf("修改失败\n");
        }
    }
    return;
}


/**************************************
 *函数名：admin_adduser
 *参   数：消息结构体
 *功   能：管理员创建用户
 ****************************************/
void do_admin_adduser(int sockfd,MSG *msg)//管理员添加用户
{		
    printf("------------%s-----------%d.\n",__func__,__LINE__);
    //让用户输入信息
    printf("please input id >   ");scanf("%d",&msg->info.no);while(getchar()!='\n');
    printf("please input usertype > ");scanf("%d",&msg->info.usertype);while(getchar()!='\n');
    printf("please input name > ");scanf("%s",msg->info.name);while(getchar()!='\n');
    printf("please input passwd > ");scanf("%s",msg->info.passwd);while(getchar()!='\n');
    printf("please input age > ");scanf("%d",&msg->info.age);while(getchar()!='\n');
    printf("please input phone > ");scanf("%s",msg->info.phone);while(getchar()!='\n');
    printf("please input addr > ");scanf("%s",msg->info.addr);while(getchar()!='\n');
    printf("please input work  > ");scanf("%s",msg->info.work );while(getchar()!='\n');
    printf("please input date > ");scanf("%s",msg->info.data);while(getchar()!='\n'); 
    printf("please input level > ");scanf("%d",&msg->info.level);while(getchar()!='\n');
    printf("please input salary > ");scanf("%lf",&msg->info.salary);while(getchar()!='\n');
    
    msg->msgtype = ADMIN_ADDUSER;
    //printf("run to %d \n",__LINE__);
    //发送信息
    if(send(sockfd,msg,sizeof(MSG),0) == -1)
    {
        printf("fail to send\n"); 
        return; 
    }
    //printf("run to %d\n",__LINE__);
    //判断是否插入成功
    if(recv(sockfd,msg,sizeof(MSG),0) == -1)
    {
        printf("fail to recv\n");  
    }
    if(strcmp(msg->recvmsg,"ROK") == 0)
    {
        printf("--------------------add success------------------------\n");
    }else{
        printf("fail to add\n");
    }

    return;
}


/**************************************
 *函数名：admin_deluser
 *参   数：消息结构体
 *功   能：管理员删除用户
 ****************************************/
void do_admin_deluser(int sockfd,MSG *msg)//管理员删除用户
{
    printf("------------%s-----------%d.\n",__func__,__LINE__);

    int num,id;
    //输入要修改的ID,看是否存在该人
    puts("请输入您要删除的ID:");
    scanf("%d",&id);
    getchar();
    //发送ID，并确定是否存在
    msg->info.no = id;
    msg->msgtype = ADMIN_DELUSER;
    if(send(sockfd,msg,sizeof(MSG),0) == -1){
        printf("发送失败 %d \n",__LINE__);
        return;
    }
    if (recv(sockfd,msg,sizeof(MSG),0) == -1)
    {
        printf("fail to recv\n");
    }
    if (strncmp(msg->recvmsg,"DEL",3) == 0)
    {
        printf("--------------------删除成功------------------------\n");
    }
    else{
        printf("用户不存在，删除失败\n");
        return;
    }

    return;
}


/**************************************
 *函数名：do_history
 *参   数：消息结构体
 *功   能：查看历史记录
 ****************************************/
void do_admin_history (int sockfd,MSG *msg)
{
    printf("------------%s-----------%d.\n",__func__,__LINE__);
    msg->msgtype = ADMIN_HISTORY;
    if(send(sockfd, msg, sizeof(MSG), 0) < 0){
        perror("send()");
        return;
    }
    printf("发送查询历史信息成功,等待接收。\n");
    printf(" 时间       姓名      事件\n");
    while(1)
    {
        //获取信息
        if(recv(sockfd, msg, sizeof(MSG), 0) < 0){
            perror("recv()");
            return;
        }
        if(strncmp(msg->recvmsg,"NO",2) == 0){
            printf("暂无历史信息\n");
            return;
        }
        else if(strncmp(msg->recvmsg,"HST",3) == 0)
        {
            printf("接收结束\n");
            break;
        }
        else
        {            
            //打印所有信息
            printf("%s\n", msg->recvmsg);        
        }
        //while(1);
    }
    return;
}

int admin_choose;
//管理员身份登入
void do_mode_admin(int sockfd, MSG *msg)
{
    printf("进入管理员模式>>\n");
    Login_inf(sockfd,msg);

    msg->usertype = ADMIN;
    if(send(sockfd,msg,sizeof(MSG),0) < 0){
        perror("send()");
        return;
    }
    //printf("send ok   ---  %s  %d\n",msg->info.name,__LINE__);

    //判断是否发送成功
    recv(sockfd,msg,sizeof(MSG),0);
    if(strncmp(msg->recvmsg,"OKOK",2) == 0)
    {
        while(1)
        {
            //注册登入
            printf("登入成功,亲爱的管理员，欢迎您登陆员工管理系统！\n");
    ret1:
            printf("**********************************************************************\n");
            printf("* 1：查询  2：修改 3：添加用户  4：删除用户  5：查询历史记录  6：退出*\n");
            printf("**********************************************************************\n");

            //-----------管理员模式菜单选择---------------//
            printf("请输入选项\n");
            scanf("%d", &admin_choose);
            getchar();
            printf("%d\n",admin_choose);
            switch (admin_choose)
            {
            case 1://查询
                do_admin_query(sockfd, msg);
                break;
            case 2://修改
                do_admin_modification(sockfd,msg);
                break;
            case 3://添加用户
                do_admin_adduser(sockfd,msg);
                break;
            case 4://删除用户
                do_admin_deluser(sockfd,msg);
                break;
            case 5://查询历史信息
                do_admin_history(sockfd,msg);
                break;
            case 6://退出
                //exit(1);
                goto out;
            default:
                printf("****** 您输入的有误，请重新输入  do_mode _admin******\n");
                goto ret1;
                break;
            }  
            //break;          
        }
    }
    else
    {
        printf("登入失败\n");
        return;
    }
out:
    printf("管理员模式退出\n");
}

//--------------------普通员工信息------------//
/**************************************
 *函数名：do_query
 *参   数：消息结构体
 *功   能：登陆
 ****************************************/
void do_user_query(int sockfd,MSG *msg)
{
    //发送封装后的结构体
    msg->msgtype = USER_QUERY;
    strcpy(msg->recvmsg,user_name);
    if(send(sockfd, msg, sizeof(MSG), 0) < 0){
        perror("send()");
        return;
    }
    printf("发送查询%s信息成功,等待接收。\n",user_name);
    //获取信息
    if(recv(sockfd, msg, sizeof(MSG), 0) < 0){
        perror("recv()");
        return;
    }
    if(strncmp(msg->recvmsg,"NOUSER",6) == 0){
        printf("查询失败\n");
        return;
    }
    else
    {
        //获取信息
        printf("工号   用户类型    姓名   密码   年龄   电话   地址   职位 入职年月   等级   工资\n");
        //打印所有信息
        printf("%-8d %-6d %-6s %-6s %-6d %-6s %-6s %-6s %-6s %-6d %-6f\n",\
            msg->info.no,msg->info.usertype,msg->info.name,msg->info.passwd,msg->info.age,msg->info.phone,\
            msg->info.addr,msg->info.work,msg->info.data,msg->info.level,msg->info.salary);
    } 
    //打印信息
    //printf("%s",msg->recvmsg);

}


/**************************************
 *函数名：do_modification
 *参   数：消息结构体
 *功   能：修改
 ****************************************/
void do_user_modification(int sockfd,MSG *msg)
{
    printf("------------%s-----------%d.\n",__func__,__LINE__);
    //输入要修改的信息
    int id,num;
    printf("请输入您的ID:\n");
    scanf("%d",&msg->info.no);
    getchar();
Modify:
    printf("请选择要修改的信息\n");
    puts("*******************请输入要修改的选项********************");
    puts("******	1：姓名	   2：密码	3：年龄       4：电话  *****");
    puts("******	5：地址	   6：职位  7：入职年月   8：评级   ****");
    puts("******	9：工资	  10：退出				           ****");
    puts("********************************************************");
    printf("请输入您的选择（1~10）>> ");
    scanf("%d",&num);
    getchar();
    //根据选择发送不同修改信息
    switch (num)
    {
    case 1:
        msg->flags = 1;
        printf("请输入姓名>> ");
        scanf("%s",msg->info.name);getchar();
        break;
    case 2:
        msg->flags = 2;
        printf("请输入密码>> ");
        scanf("%s",msg->info.passwd);getchar();
        break;
    case 3:
        msg->flags = 3;
        printf("请输入年龄>> ");
        scanf("%d",&msg->info.age);getchar();
        break;
    case 4:
        msg->flags = 4;
        printf("请输入电话>> ");
        scanf("%s",msg->info.phone);getchar();
        break;
    case 5:
        msg->flags = 5;
        printf("请输入地址>> ");
        scanf("%s",msg->info.addr);getchar();
        break;
    case 6:
        msg->flags = 6;
        printf("请输入职位>> ");
        scanf("%s",msg->info.work);getchar();
        break;
    case 7:
        msg->flags = 7;
        printf("请输入入职年月>> ");
        scanf("%s",msg->info.data);getchar();
        break;
    case 8:
        msg->flags = 8;
        printf("请输入等级>> ");
        scanf("%d",&msg->info.level);getchar();
        break;
    case 9:
        msg->flags = 9;
        printf("请输入工资>> ");
        scanf("%lf",&msg->info.salary);getchar();
        break;
    case 10:
        break;
    default:
        printf("输入错误，请重新输入\n");getchar();
        goto Modify;
        break;
    }
    //发送消息
    msg->msgtype = USER_MODIFY;
    
    //printf("run to %d \n",__LINE__);
    if (send(sockfd,msg,sizeof(MSG),0) == -1)
    {
        printf("fail to send \n");
        return;
    }else{
        if (recv(sockfd,msg,sizeof(MSG),0) == -1)
        {
            printf("fail to recv\n");
            return;
        }
        else{
            if (strncmp(msg->recvmsg,"YES",3) == 0)
            {
                printf("--------------------修改成功------------------------\n");
                return;
            }
            printf("修改失败\n");
        }
    }
    

    return;
}

//普通员工登入
void do_mode_user(int sockfd, MSG *msg)
{
    int user_choose;
    printf("进入普通用户模式>>\n");

    Login_inf(sockfd,msg);
    while(1)
    {
        printf("*************************************************************\n");
        printf("* *************  1：查询  	2：修改	 3：退出     ************\n");
        printf("*************************************************************\n");

        //-----------普通用户模式菜单选择---------------//
        printf("请选择您要操作的选项！\n");
        scanf("%d", &user_choose);
        getchar();

        switch (user_choose)
        {
            case 1://查询
                do_user_query(sockfd,msg);
                break;
            case 2://修改
                do_user_modification(sockfd,msg);
                break;
            case 3://退出
                //需要补充
                goto next;
                break;
            default:
                printf("****** 您输入的有误，请重新输入 do_mode_user ******\n");
                break;
        }
    }
next:
    printf("退出普通员工模式\n");
}

//将用户名和密码发送到服务器数据库对比
int Login_inf(int socked, MSG *msg)
{
    printf("请输入用户名\n");
    scanf("%s",msg->username);
    getchar();
    strcpy(user_name,msg->username);
    printf("请输入密码\n");
    scanf("%s",msg->passwd);
    getchar();
    printf("输入完成\n");
    // msg->msgtype = ADMIN;
    return 0;
}


int main(int argc, const char *argv[])
{
    if(argc != 3){
        printf("Usage: <%s> <port>",argv[0]);
        exit(1);
    } 

    //创建套接子
    int socket_fd;
    socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    if(socket_fd < 0){
        perror("socket()");
        return -1;
    }


    //填充网络信息结构体
    struct sockaddr_in serveraddr,clientaddr;
    bzero(&serveraddr, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port   = htons(atoi(argv[1]));
    serveraddr.sin_addr.s_addr = inet_addr(argv[2]);

    // printf("%d \n",serveraddr.sin_port);
    //connect连接
    int ret;
    connect(socket_fd,(const struct sockaddr *)(&serveraddr), sizeof(serveraddr));
    if(ret < 0){
        perror("connect()");
        return -1;
    }

    //局部变量
    char num;
    MSG msg;


    while(1)
    {
tryone:
        printf("*************************************************************\n");
        printf("********  1：管理员模式    2：普通用户模式     3：退出********\n");
        printf("*************************************************************\n");
        printf("*************************************************************\n");
        scanf("%c", &num);
        getchar();
        switch (num)
        {
        case '1':
            printf("即将进入管理员模式>>\n");
            do_mode_admin(socket_fd, &msg);
            break;
        case '2':
            printf("即将进入普通用户模式>>\n");
            do_mode_user(socket_fd, &msg);
            break;
        case '3':
            //strcpy(msg.recvmsg,"QUIT");
            msg.msgtype = QUIT;
            send(socket_fd,&msg,sizeof(MSG),0);
            goto exit;
            break;
        default:
            printf("****** 您输入的有误，请重新输入 ******\n");
            goto tryone;
            break;
        }
        //清除mag结构体
        bzero(&msg,sizeof(MSG));
    }
exit:
    close(socket_fd);
    printf("客户端退出了\n");
    return 0;
}
















